module Miscellaneous_utilities where

-- ceiling(a/b).  Not sure about negatives.
div_ceil :: Integral a => a -> a -> a
div_ceil a b = 1 + ((a - 1) `div` b)

-- round(a/b).  Not sure about negatives. .5 should round up.
div_round :: Integral a => a -> a -> a
div_round a b = if r >= (b `div` 2) then q + 1 else q
    where
      q = a `div` b
      r = a `rem` b

-- Like List.map, but the function takes an index as well
mapi :: Num t => (t -> a -> b) -> [a] -> [b]
mapi f l = reverse l'
    where
      (_,l') = foldl (\(i,acc) x -> (i+1,(f i x):acc)) (0,[]) l

-- Like fold, but operates on pairs of consecutive elements
-- foldl_pairs f i [x1,x2,x3,x4] -> f( f( f i x1 x2 ) x2 x3 ) x3 x4
foldl_pairs :: (b -> a -> a -> b) -> b -> [a] -> b
foldl_pairs acc ini l =
    case l of
      [] -> ini
      f:r -> foldl_pairs_helper ini f r
          where
            foldl_pairs_helper v _ [] = v
            foldl_pairs_helper v prev (next:rest) =
                foldl_pairs_helper (acc v prev next) next rest

